package com.lgl.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lgl.constants.SystemConstants;
import com.lgl.entity.Menu;
import com.lgl.entity.ResponseResult;
import com.lgl.entity.Role;
import com.lgl.entity.RoleMenu;
import com.lgl.enums.AppHttpCodeEnum;
import com.lgl.exception.SystemException;
import com.lgl.mapper.MenuMapper;
import com.lgl.service.MenuService;
import com.lgl.service.RoleMenuService;
import com.lgl.service.RoleService;
import com.lgl.utils.BeanCopyUtils;
import com.lgl.utils.SecurityUtils;
import com.lgl.vo.GetMenuVo;
import com.lgl.vo.MenuTreeSelectVo;
import com.lgl.vo.MenuVo;
import com.lgl.vo.RoleMenuTreeselectVo;
import lombok.experimental.Accessors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service("menuService")
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
    @Autowired
    private RoleService roleService;
    @Autowired
    private RoleMenuService roleMenuService;


    @Override
    public List<String> selectPermsByUserId(Long id) {
        //如果是管理员，返回所有的权限
        if (id == 1L) {
            LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(Menu::getMenuType, SystemConstants.MENU, SystemConstants.BUTTON);
            wrapper.eq(Menu::getStatus, SystemConstants.STATUS_NORMAL);
            List<Menu> menus = list(wrapper);
            List<String> perms = menus.stream()
                    .map(Menu::getPerms)
                    .collect(Collectors.toList());
            return perms;
        }
        //否则返回所具有的权限
        return getBaseMapper().selectPermsByUserId(id);
    }

    @Override
    public List<Menu> selectRouterMenuTreeByUserId(Long userId) {
        MenuMapper menuMapper = getBaseMapper();
        List<Menu> menus = null;
        //判断是否是管理员
        if (SecurityUtils.isAdmin()) {
            //如果是 获取所有符合要求的Menu
            menus = menuMapper.selectAllRouterMenu();
        } else {
            //否则  获取当前用户所具有的Menu
            menus = menuMapper.selectRouterMenuTreeByUserId(userId);
        }

        //构建tree
        //先找出第一层的菜单  然后去找他们的子菜单设置到children属性中
        List<Menu> menuTree = builderMenuTree(menus, 0L);
        return menuTree;
    }

    @Override
    public ResponseResult menuList(String status, String menuName) {
//   需要展示菜单列表，不需要分页。
//	可以针对菜单名进行模糊查询//
//	也可以针对菜单的状态进行查询。
//	菜单要按照父菜单id和orderNum进行排序
        LambdaQueryWrapper<Menu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasText(menuName), Menu::getMenuName, menuName);
        queryWrapper.eq(StringUtils.hasText(status), Menu::getStatus, status);
        queryWrapper.orderByAsc(Menu::getParentId, Menu::getOrderNum);
        List<Menu> list = list(queryWrapper);
        List<MenuVo> menuVos = BeanCopyUtils.copyBeanList(list, MenuVo.class);
        return ResponseResult.okResult(menuVos);
    }


    @Override
    @Transactional
    public ResponseResult addMenu(Menu menu) {
        save(menu);
        List<Role> roles = roleService.selectRoleByUserId(SecurityUtils.getUserId());
        for (Role role : roles) {
            RoleMenu roleMenu = new RoleMenu(role.getId(), menu.getId());
            roleMenuService.save(roleMenu);
        }
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult getMenuById(Long id) {
        Menu menu = getById(id);
        GetMenuVo getMenuVo = BeanCopyUtils.beanCopy(menu, GetMenuVo.class);
        return ResponseResult.okResult(getMenuVo);
    }

    @Override
    @Transactional
    public ResponseResult updateMenu(Menu menu) {
        if (menu.getParentId().equals(menu.getId())) {
            throw new SystemException(AppHttpCodeEnum.UPDATE_MENU_ERROR);
        }
        updateById(menu);
        return ResponseResult.okResult();
    }

    @Override
    @Transactional
    public ResponseResult deleteMenu(Long id) {
        Menu menu = getById(id);
        List<Menu> menuList = list();

        if (!CollectionUtils.isEmpty(getChildren(menu, menuList))) {
            throw new SystemException(AppHttpCodeEnum.SUBMENU_EXISTS);
        }
        removeById(id);
        List<Role> roles = roleService.selectRoleByUserId(SecurityUtils.getUserId());
        for (Role role : roles) {
            LambdaQueryWrapper<RoleMenu> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(RoleMenu::getMenuId, id);

            roleMenuService.remove(queryWrapper);
        }
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult Treeselect() {
        LambdaQueryWrapper<Menu> menuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        menuLambdaQueryWrapper.eq(Menu::getStatus,SystemConstants.STATUS_NORMAL);
        List<Menu> list = list(menuLambdaQueryWrapper);
        List<Menu> menuList = builderMenuTree(list, 0L);
        List<MenuTreeSelectVo> menuTreeSelectVos = beanCopy(menuList);
        return ResponseResult.okResult(menuTreeSelectVos);
    }

    @Override
    public ResponseResult roleMenuTreeselect(Long id) {
//
        LambdaQueryWrapper<Menu> menuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        menuLambdaQueryWrapper.eq(Menu::getStatus,SystemConstants.STATUS_NORMAL);
        List<Menu> list = list(menuLambdaQueryWrapper);
        List<Menu> menuList = builderMenuTree(list, 0L);
        List<MenuTreeSelectVo> menuTreeSelectVos = beanCopy(menuList);
        LambdaQueryWrapper<RoleMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RoleMenu::getRoleId,id);
        List<RoleMenu> roleMenus = roleMenuService.list(queryWrapper);
        List<Long> arrayList = new ArrayList<>();
        for (RoleMenu roleMenu : roleMenus) {
            arrayList.add(roleMenu.getMenuId());
        }
        RoleMenuTreeselectVo roleMenuTreeselectVo = new RoleMenuTreeselectVo(menuTreeSelectVos, arrayList);

        return ResponseResult.okResult(roleMenuTreeselectVo);
    }

    private List<MenuTreeSelectVo> beanCopy(List<Menu> list) {
        ArrayList<MenuTreeSelectVo> menuTreeSelectVos = new ArrayList<>();
        for (Menu menu : list) {
            MenuTreeSelectVo menuTreeSelectVo = new MenuTreeSelectVo(menu.getId(), menu.getParentId(), menu.getMenuName(), beanCopy(menu.getChildren()));
            menuTreeSelectVos.add(menuTreeSelectVo);
        }
        return menuTreeSelectVos;
    }

    private List<Menu> builderMenuTree(List<Menu> menus, Long parentId) {
        List<Menu> menuTree = menus.stream()
                .filter(menu -> menu.getParentId().equals(parentId))
                .map(menu -> menu.setChildren(getChildren(menu, menus)))
                .collect(Collectors.toList());
        return menuTree;
    }

    /**
     * 获取存入参数的 子Menu集合
     *
     * @param menu
     * @param menus
     * @return
     */
    private List<Menu> getChildren(Menu menu, List<Menu> menus) {
        List<Menu> childrenList = menus.stream()
                .filter(m -> m.getParentId().equals(menu.getId()))
                .map(m -> m.setChildren(getChildren(m, menus)))
                .collect(Collectors.toList());
        return childrenList;
    }
}